package opensave

import (
	"path/filepath"
)

type EditingState struct {
	Status    EditingStatus
	FilePath  string
}
type EditingStatus int
const (
	Idle EditingStatus = iota
	NewDoc
	Clean
	Dirty
)
type EditingStateListener func(EditingState)

type SingletonEditor struct {
	EditingState
	EditingStateListener
}
func NewSingletonEditor(initial_path string, listener EditingStateListener) *SingletonEditor {
	var state = (func() EditingState {
		if initial_path != "" {
			return EditingState {
				Status:   Clean,
				FilePath: initial_path,
			}
		} else {
			return EditingState {
				Status:   Idle,
				FilePath: "",
			}
		}
	})()
	return &SingletonEditor {
		EditingState:         state,
		EditingStateListener: listener,
	}
}
func (e *SingletonEditor) Refresh() {
	e.EditingStateListener(e.EditingState)
}
func (e *SingletonEditor) BaseDir() string {
	return filepath.Dir(e.EditingState.FilePath)
}
func (e *SingletonEditor) State() EditingState {
	return e.EditingState
}
func (e *SingletonEditor) changeStatus(status EditingStatus) {
	e.Status = status
	e.EditingStateListener(e.EditingState)
}
func (e *SingletonEditor) changeStatusAndPath(status EditingStatus, path string) {
	e.Status = status
	e.FilePath = path
	e.EditingStateListener(e.EditingState)
}
func (e *SingletonEditor) NotifyMutation() {
	switch e.Status {
	case Idle:
		e.changeStatus(NewDoc)
	case Clean:
		e.changeStatus(Dirty)
	default:
		// do nothing
	}
}
func (e *SingletonEditor) New(confirm func()(bool), k func()) {
	switch e.Status {
	case NewDoc, Dirty:
		if !(confirm()) {
			return
		} else {
			// discard current content
		}
	}
	k()
	e.changeStatusAndPath(Idle, "")
}
func (e *SingletonEditor) Open(confirm func()(bool), k func()(string,bool,error)) error {
	switch e.Status {
	case NewDoc, Dirty:
		if !(confirm()) {
			return nil
		} else {
			// discard current content if open operation not cancelled
		}
	}
	var path, proceed, err = k()
	if err != nil { return err }
	if !(proceed) { return nil } // cancelled
	e.changeStatusAndPath(Clean, path)
	return nil
}
func (e *SingletonEditor) Save(get_path func()(string,bool), k func(string)(error)) error {
	switch e.Status {
	case NewDoc:
		var path, ok = get_path()
		if ok {
			var err = k(path)
			if err != nil { return err }
			e.changeStatusAndPath(Clean, path)
			return nil
		} else {
			// cancelled
			return nil
		}
	case Dirty:
		var err = k(e.FilePath)
		if err != nil { return err }
		e.changeStatus(Clean)
		return nil
	default:
		// do nothing
		return nil
	}
}
func (e *SingletonEditor) Quit(confirm func()(bool), k func()) {
	switch e.Status {
	case NewDoc, Dirty:
		if !(confirm()) {
			return
		} else {
			// discard current content
		}
	}
	k()
}


